home *** CD-ROM | disk | FTP | other *** search
-
-
- /*
- How to make the MT-02 SCSI tape drive useable ...
-
- *****This post has no warranty*****
-
- NeXT Answers hardware.762 gives details of how to set the NeXT st
- driver into fixed block mode, allowing it to work with QIC style tape
- drives. This has enabled my tape drive to work, but my drive has
- performed badly, often bombing out with write errors. I knew it wasn't
- the drive or the media because they both work when connected to a sun,
- and the tape works in other drives. The clue came from the NeXT
- Console where I found the following message.
-
- st: cmd = 0xa sr_io_status = 2H
- Sense key = 0x1 Sense Code = 0x0
-
- A sense key of 0x1 indicates a recoverable error, ie one that the tape
- drive fixed, e.g. a write failed but was sucessful on a subsequent
- retry (provided the max retry limit wasn't reached). Some tape drivers
- report the number of recoverable errors, and on some machines "mt
- status" will report the number.
-
- Anyway it turns out that the MT-02 tape controller has a bit which
- controls how it handles soft errors. The default case when connected
- to a NeXT is to for the tape drive to issue a CHECK CONDITION status
- code after it executes a command if a recoverable error occured. The
- NeXT st driver seems to handle this as if it were a real error and
- bombs out at this point. The other mode is to have the drive
- accumulate the number of soft errors, so that they can be collected
- later by the REQUEST SENSE command.
-
- The following tape utility adds to the code in NA.762 and gives the
- option of setting the SEC bit. It also allows the user to set the
- driver back to variable block mode, and execute the MODE SENSE and
- REQUEST SENSE scsi commands.
-
-
-
- Mark Andrews
- abekas!mark@pyramid.com <non-NeXT mail>
- abekas!cookie!mark@pyramid.com <NeXT mail ok>
-
- */
-
-
- /* */
- /* NeXT scsi tape driver utility */
- /* Mark Andrews 1992 */
- /* This Code is Supplied as is with NO WARRANTY of any kind */
- /* No resposibility can or will be accepted for any damage that using */
- /* this program may cause */
- /* It has only been tested on a SCSI tape drive with an MT-02 tape controller */
- /* Note the SEC bit is part of the VENDOR unique stuff and may or may not */
- /* work with other drives. In particular it doesn't work with Exabyte. */
- /* The MTIOCFIXBLK code is from NA.562 */
- /* The REQUEST SENSE code is from a posting by louie@sayshell.umd.edu 3/10/92 */
- /* */
-
- #include <stdio.h>
- #include <libc.h>
- #include <sys/types.h>
- #include <sys/file.h>
- #include <sys/mtio.h>
- #include <nextdev/scsireg.h>
-
- #define SEC 0x1
- #define QUIET 0
- #define VERBOSE 1
-
- char *tape_name;
- int tape;
- struct modesel_parms msp;
- struct scsi_req sr;
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- char c;
- int sf,sv,ms,rs,sc;
-
- sf=sv=ms=rs=sc=0;
-
-
-
-
- /* strcpy(tape_name,"/dev/rst0");*/
- tape_name=getenv("TAPE");
- if (tape_name == 0) tape_name = "/dev/nrxt0" ;
-
-
-
- while((c=getopt(argc,argv,"hvrmsf:b:")) !=EOF)
- {
- if(c=='f') strcpy(tape_name,optarg);/* set device from cmd lineman */
- if(c=='b') if(optarg!=NULL)sf=atoi(optarg);else sf=512; /* set to fixed block mode */
- if(c=='v') sv=1; /* set to variable block mode */
- if(c=='m') ms=1; /* mode sense */
- if(c=='r') rs=1; /* request sense */
- if(c=='s') sc=1; /* set the soft error bit */
- if(c=='h') /* print usage */
- fprintf(stderr,"Usage: %s -hvrmsnf [block size]\n%s%s%s%s%s%s%s",argv[0],
- "\t-h : print usage,\n",
- "\t-b # : set fixed block mode with size #,\n",
- "\t-v : set variable block mode,\n",
- "\t-m : do a mode sense command and report the results,\n",
- "\t-r : do a request sense command and report the results,\n",
- "\t-s : set the soft error bit, (not valid on exabyte)\n",
- "\t-f : use device named.\n");
- }
-
- printf("Using tape drive: %s\n",tape_name);
-
- /* open /dev/rxt0 */
- if((tape=open(tape_name,O_RDWR,777))==0)
- {
- fprintf(stderr,"Unable to open %s\n",*tape_name);
- exit(1);
- }
-
- if(sv)
- {
- if(!sf)
- set_var_blk();
- else
- {
- fprintf(stderr,"Can't set to both fixed and variable block mode\n");
- problem();
- }
- }
- if(sf) set_fix_blk(sf);
- if(ms) mode_sense(VERBOSE);
- if(rs) request_sense();
- if(sc) set_sec();
-
- /* close tape */
- close (tape);
- exit(0);
- }
-
- problem()
- {
- /* close tape */
- close (tape);
- exit(-1);
- }
-
- mode_sense(verbose)
- int verbose;
- {
- /* do a mode sense ioctl */
- msp.msp_bcount=17; /* think this is correct */
- if(ioctl(tape,MTIOCMODSEN,&msp))
- {
- perror("mode sense ioctl failed\n");
- exit(1);
- }
- if(!verbose)
- return;
- /* print out the returned data */
- fprintf(stdout,"mode sense data length = %d\n",(int)msp.msp_data.msd_header.msh_sd_length_0);
- fprintf(stdout,"media type = %d\n",(int)msp.msp_data.msd_header.msh_med_type);
- if(msp.msp_data.msd_header.msh_wp)
- fprintf(stdout,"tape is = write protected\n");
- else
- fprintf(stdout,"tape is = writeable\n");
-
- fprintf(stdout,"buffered mode = %d\n",(int)msp.msp_data.msd_header.msh_bufmode);
- fprintf(stdout,"speed = %d\n",(int)msp.msp_data.msd_header.msh_speed);
- fprintf(stdout,"block descriptor length = %d\n",(int)msp.msp_data.msd_header.msh_bd_length);
- fprintf(stdout,"density code = %d\n",(int)msp.msp_data.msd_blockdescript.msbd_density);
- fprintf(stdout,"number of blocks = %d\n",(int)msp.msp_data.msd_blockdescript.msbd_numblocks);
- fprintf(stdout,"block length = %d\n",(int)msp.msp_data.msd_blockdescript.msbd_blocklength);
- fprintf(stdout,"vendor unique byte[0] = %d\n",(int)msp.msp_data.msd_vudata[0]);
- fprintf(stdout,"vendor unique byte[1] = %d\n",(int)msp.msp_data.msd_vudata[1]);
- fprintf(stdout,"vendor unique byte[2] = %d\n",(int)msp.msp_data.msd_vudata[2]);
- fprintf(stdout,"vendor unique byte[3] = %d\n",(int)msp.msp_data.msd_vudata[3]);
- fprintf(stdout,"vendor unique byte[4] = %d\n",(int)msp.msp_data.msd_vudata[4]);
- }
-
- mode_slct()
- {
- /* this routine assumes that the msp structure has already been */
- /* initialized, a mode_sense is the best way to do this */
-
- /* do a mode select ioctl */
- if(ioctl(tape,MTIOCMODSEL,&msp))
- {
- perror("mode select ioctl failed\n");
- return 1;
- }
- }
-
- set_sec()
- {
-
- mode_sense(QUIET); /* do a mode sense */
- msp.msp_data.msd_vudata[0]|=SEC; /* set the SEC bit */
- fprintf(stdout,"setting no report for soft errors\n");
- mode_slct(); /* do a mode select */
- }
-
- set_fix_blk(blocksize)
- int blocksize;
- {
-
- if(ioctl(tape,MTIOCFIXBLK,&blocksize))
- {
- perror("fixed block ioctl failed\n");
- return 1;
- }
- /* The following section added to set the drive to be the same as */
- /* the driver. sgb */
- msp.msp_data.msd_blockdescript.msbd_blocklength=blocksize;
- fprintf(stdout,"tape is set for fixed blocks of %i\n",blocksize);
-
- mode_slct();
- }
-
-
- set_var_blk()
- {
-
- if(ioctl(tape,MTIOCVARBLK))
- {
- perror("variable block ioctl failed\n");
- return 1;
- }
- /* The following section added to set the drive to be the same as */
- /* the driver. sgb */
- fprintf(stdout,"tape is set for variable blocks\n");
- msp.msp_data.msd_blockdescript.msbd_blocklength=0;
- mode_slct();
-
- }
-
- request_sense()
- {
- /* set up sr */
- bzero(&sr, sizeof(sr));
- sr.sr_dma_dir=SR_DMA_RD;
- sr.sr_dma_max=sizeof(sr.sr_esense);
- sr.sr_addr=(caddr_t)&sr.sr_esense;
- sr.sr_ioto=2;
- sr.sr_cdb.cdb_c6.c6_opcode=C6OP_REQSENSE;
- sr.sr_cdb.cdb_c6.c6_len=sizeof(sr.sr_esense);
-
- /* execute the request sense */
- if(ioctl(tape,MTIOCSRQ,&sr))
- {
- perror("request sense ioctl failed\n");
- return 1;
- }
-
- /* print the answers */
- fprintf(stdout,"io status = %d\n",(int)sr.sr_io_status);
- fprintf(stdout,"scsi status = %d\n",(int)sr.sr_scsi_status);
- fprintf(stdout,"bytes dma'd = %d\n",(int)sr.sr_dma_xfr);
- fprintf(stdout,"sense info bytes are =");
- if(sr.sr_esense.er_ibvalid)
- fprintf(stdout,"valid\n");
- else
- fprintf(stdout,"not valid\n");
- fprintf(stdout,"error class = %d\n",(int)sr.sr_esense.er_class);
- fprintf(stdout,"error code = %d\n",(int)sr.sr_esense.er_code);
- fprintf(stdout,"segment number = %d\n",(int)sr.sr_esense.er_segment);
- fprintf(stdout,"file mark found = ");
- if(sr.sr_esense.er_filemark)
- fprintf(stdout,"yes\n");
- else
- fprintf(stdout,"no\n");
- fprintf(stdout,"end of medium = ");
- if(sr.sr_esense.er_endofmedium)
- fprintf(stdout,"yes\n");
- else
- fprintf(stdout,"no\n");
- fprintf(stdout,"incorect length = ");
- if(sr.sr_esense.er_badlen)
- fprintf(stdout,"yes\n");
- else
- fprintf(stdout,"no\n");
- fprintf(stdout,"sense key = %d\n",(int)sr.sr_esense.er_sensekey);
- fprintf(stdout,"residue length = %d\n",(int)sr.sr_esense.er_info+((int)sr.sr_esense.er_infomsb<<24));
- fprintf(stdout,"additional sense length = %d\n",(int)sr.sr_esense.er_addsenselen);
- fprintf(stdout,"additional sense code = %d\n",(int)sr.sr_esense.er_addsensecode);
- fprintf(stdout,"sense code qualifier = %d\n",(int)sr.sr_esense.er_qualifier);
- fprintf(stdout,"status byte 13 = %d\n",(int)sr.sr_esense.er_stat_13);
- fprintf(stdout,"status byte 14 = %d\n",(int)sr.sr_esense.er_stat_14);
- fprintf(stdout,"status byte 15 = %d\n",(int)sr.sr_esense.er_stat_15);
- fprintf(stdout,"recoverable errors = %d\n",(int)sr.sr_esense.er_err_count);
- }
-
- /* Additional Credits:*/
- /* nigelm@ohm.york.ac.uk (Nigel Metheringham)*/
- /* bug in -f setting*/
- /* consisting in printing what drive is being used.*/
-
-